<script>
import BrandImage from '@/components/BrandImage';
import RancherProviderIcon from '@/components/RancherProviderIcon';
import { mapGetters } from 'vuex';
import $ from 'jquery';
import { MANAGEMENT } from '@/config/types';
import { mapPref, DEV, MENU_MAX_CLUSTERS } from '@/store/prefs';
import { sortBy } from '@/utils/sort';
import { ucFirst } from '@/utils/string';
import { KEY } from '@/utils/platform';
import { getVersionInfo } from '@/utils/version';
import { LEGACY } from '@/store/features';
import { SETTING } from '@/config/settings';

const UNKNOWN = 'unknown';
const UI_VERSION = process.env.VERSION || UNKNOWN;
const UI_COMMIT = process.env.COMMIT || UNKNOWN;

export default {

  components: { BrandImage, RancherProviderIcon },

  data() {
    const { displayVersion, fullVersion } = getVersionInfo(this.$store);

    return {
      shown:          false,
      displayVersion,
      fullVersion,
      uiCommit:       UI_COMMIT,
      uiVersion:      UI_VERSION,
      clusterFilter:  '',
    };
  },

  computed: {
    ...mapGetters(['clusterId']),
    ...mapGetters(['clusterReady', 'isRancher', 'currentCluster', 'currentProduct']),
    ...mapGetters('type-map', ['activeProducts']),
    ...mapGetters('i18n', ['selectedLocaleLabel', 'availableLocales']),
    ...mapGetters({ features: 'features/get' }),

    value: {
      get() {
        return this.$store.getters['productId'];
      },
    },

    legacyEnabled() {
      return this.features(LEGACY);
    },

    showClusterSearch() {
      const all = this.$store.getters['management/all'](MANAGEMENT.CLUSTER);

      return all.length > this.maxClustersToShow;
    },

    clusters() {
      const all = this.$store.getters['management/all'](MANAGEMENT.CLUSTER);
      let out = all.map((x) => {
        return {
          id:      x.id,
          label:   x.nameDisplay,
          ready:   x.isReady,
          osLogo:  x.providerOsLogo,
          logo:    x.providerLogo,
          isLocal: x.isLocal
        };
      });

      const search = (this.clusterFilter || '').toLowerCase();

      if ( search ) {
        out = out.filter(item => item.label.toLowerCase().includes(search));
      }

      const sorted = sortBy(out, ['ready:desc', 'label']);

      return sorted;
    },

    dev: mapPref(DEV),

    maxClustersToShow: mapPref(MENU_MAX_CLUSTERS),

    showLocale() {
      return Object.keys(this.availableLocales).length > 1 || this.dev;
    },

    showNone() {
      return this.dev;
    },

    multiClusterApps() {
      const options = this.options;

      return options.filter(opt => opt.inStore === 'management' && opt.category !== 'configuration' && opt.category !== 'legacy');
    },

    legacyApps() {
      const options = this.options;

      return options.filter(opt => opt.inStore === 'management' && opt.category === 'legacy');
    },

    configurationApps() {
      const options = this.options;

      return options.filter(opt => opt.category === 'configuration');
    },

    options() {
      const cluster = this.clusterId || this.$store.getters['defaultClusterId'];

      const entries = this.activeProducts.map((p) => {
        // Try product-specific index first
        const to = {
          name:   `c-cluster-${ p.name }`,
          params: { cluster }
        };

        if ( !this.$router.getMatchedComponents(to).length ) {
          to.name = 'c-cluster-product';
          to.params.product = p.name;
        }

        return {
          label:     this.$store.getters['i18n/withFallback'](`product."${ p.name }"`, null, ucFirst(p.name)),
          icon:      `icon-${ p.icon || 'copy' }`,
          value:     p.name,
          removable: p.removable !== false,
          inStore:   p.inStore || 'cluster',
          weight:    p.weight || 1,
          category:  p.category || 'none',
          to,
        };
      });

      return entries;
    },

    canEditSettings() {
      return (this.$store.getters['management/schemaFor'](MANAGEMENT.SETTING)?.resourceMethods || []).includes('PATCH');
    },

    hasSupport() {
      return this.$store.getters['management/byId'](MANAGEMENT.SETTING, SETTING.SUPPORTED )?.value === 'true';
    },
  },

  watch: {
    $route() {
      this.shown = false;
    },
  },

  mounted() {
    document.addEventListener('keyup', this.handler);
  },

  beforeDestroy() {
    document.removeEventListener('keyup', this.handler);
  },

  methods: {
    // Cluster list number of items shown is configurbale via user preference
    setClusterListHeight(maxToShow) {
      const el = this.$refs.clusterList;
      const max = Math.min(maxToShow, this.clusters.length);

      if (el) {
        const $el = $(el);
        const h = 32 * max;

        $el.css('height', `${ h }px`);
      }
    },
    handler(e) {
      if (e.keyCode === KEY.ESCAPE ) {
        this.hide();
      }
    },

    hide() {
      this.shown = false;
    },

    toggle() {
      this.shown = !this.shown;
      this.$nextTick(() => {
        this.setClusterListHeight(this.maxClustersToShow);
      });
    },

    switchLocale(locale) {
      this.$store.dispatch('i18n/switchTo', locale);
    },
  }
};
</script>
<template>
  <div>
    <div class="menu" :class="{'raised': shown}" @click="toggle()">
      <svg class="menu-icon" xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0z" fill="none" /><path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z" /></svg>
    </div>
    <div v-if="shown" class="side-menu-glass" @click="hide()"></div>
    <transition name="fade">
      <div v-if="shown" class="side-menu" tabindex="-1">
        <div class="title">
          <div class="menu-spacer"></div>
          <div class="side-menu-logo">
            <BrandImage file-name="rancher-logo.svg" />
          </div>
        </div>
        <div class="body">
          <div @click="hide()">
            <nuxt-link
              class="option cluster selector home"
              :to="{ name: 'home' }"
            >
              <svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0z" fill="none" /><path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z" /></svg>
              <div>
                {{ t('nav.home') }}
              </div>
            </nuxt-link>
          </div>
          <template v-if="clusters && !!clusters.length">
            <div class="category">
              {{ t('nav.categories.explore') }}
            </div>
            <div v-if="showClusterSearch" class="search">
              <input
                ref="clusterFilter"
                v-model="clusterFilter"
                :placeholder="t('nav.search.placeholder')"
              />
              <i v-if="clusterFilter.length > 0" class="icon icon-close" @click="clusterFilter=''" />
            </div>
            <div ref="clusterList" class="clusters">
              <div v-for="c in clusters" :key="c.id" @click="hide()">
                <nuxt-link
                  v-if="c.ready"
                  class="cluster selector option"
                  :to="{ name: 'c-cluster', params: { cluster: c.id } }"
                >
                  <RancherProviderIcon v-if="c.isLocal" width="24" class="rancher-provider-icon" />
                  <img v-else :src="c.logo" />
                  <div>{{ c.label }}</div>
                </nuxt-link>
                <span v-else class="option-disabled cluster selector disabled">
                  <img :src="c.logo" />
                  <div>{{ c.label }}</div>
                </span>
              </div>
              <div v-if="clusters.length === 0" class="none-matching">
                {{ t('nav.search.noResults') }}
              </div>
            </div>
          </template>

          <template v-if="multiClusterApps.length">
            <div class="category">
              {{ t('nav.categories.multiCluster') }}
            </div>
            <div v-for="a in multiClusterApps" :key="a.label" @click="hide()">
              <nuxt-link class="option" :to="a.to">
                <i class="icon group-icon" :class="a.icon" />
                <div>{{ a.label }}</div>
              </nuxt-link>
            </div>
          </template>
          <template v-if="legacyEnabled">
            <div class="category">
              {{ t('nav.categories.legacy') }}
            </div>
            <div v-for="a in legacyApps" :key="a.label" @click="hide()">
              <nuxt-link class="option" :to="a.to">
                <i class="icon group-icon" :class="a.icon" />
                <div>{{ a.label }}</div>
              </nuxt-link>
            </div>
          </template>
          <template v-if="configurationApps.length">
            <div class="category">
              {{ t('nav.categories.configuration') }}
            </div>
            <div v-for="a in configurationApps" :key="a.label" @click="hide()">
              <nuxt-link class="option" :to="a.to">
                <i class="icon group-icon" :class="a.icon" />
                <div>{{ a.label }}</div>
              </nuxt-link>
            </div>
          </template>
          <div class="pad"></div>
        </div>
        <div class="footer">
          <div v-if="canEditSettings" @click="hide()">
            <nuxt-link :to="{name: 'support'}">
              {{ t('nav.support', {hasSupport}) }}
            </nuxt-link>
          </div>
          <div @click="hide()">
            <nuxt-link
              v-tooltip="{ content: fullVersion, classes: 'footer-tooltip' }"
              :to="{ name: 'about' }"
              class="version"
              v-html="displayVersion"
            />
          </div>
          <div v-if="showLocale">
            <v-popover
              popover-class="localeSelector"
              placement="top"
              trigger="click"
            >
              <a class="locale-chooser">
                {{ selectedLocaleLabel }}
              </a>

              <template slot="popover">
                <ul class="list-unstyled dropdown" style="margin: -1px;">
                  <li v-if="showNone" v-t="'locale.none'" class="hand" @click="switchLocale('none')" />
                  <li
                    v-for="(label, name) in availableLocales"
                    :key="name"
                    class="hand"
                    @click="switchLocale(name)"
                  >
                    {{ label }}
                  </li>
                </ul>
              </template>
            </v-popover>
          </div>
        </div>
      </div>
    </transition>
  </div>
</template>

<style scoped>
  .cluster.disabled > * {
    cursor: not-allowed;
    filter: grayscale(1);
    color: var(--muted);
  }
</style>

<style lang="scss">
  .localeSelector, .footer-tooltip {
    z-index: 1000;
  }

  .cluster {
    &.selector:not(.disabled):hover {
      color: var(--primary-hover-text);
      background: var(--primary-hover-bg);
      border-radius: 5px;
      text-decoration: none;

      .rancher-provider-icon {
        .rancher-icon-fill {
          fill: var(--primary-hover-text);;
        }
      }
    }

    .rancher-provider-icon {
      .rancher-icon-fill {
        // Should match .option color
        fill: var(--link);
      }
    }

  }

  .localeSelector {
    .popover-inner {
      padding: 10px 0;
    }

    .popover-arrow {
      display: none;
    }

    .popover:focus {
      outline: 0;
    }
  }

</style>

<style lang="scss" scoped>
  $clear-search-size: 20px;
  $icon-size: 24px;
  $option-padding: 4px;
  $option-height: $icon-size + $option-padding + $option-padding;

  .option {
    align-items: center;
    cursor: pointer;
    display: flex;
    color: var(--link);

    &:hover {
      text-decoration: none;
    }

    &:focus {
      outline: 0;
      > div {
        text-decoration: underline;
      }
    }

    > i {
      font-size: $icon-size;
      margin-right: 8px;
    }
    svg {
      margin-right: 8px;
      fill: var(--link);
    }

    > div {
      color: var(--link);
    }

    &:hover {
      color: var(--primary-hover-text);
      background: var(--primary-hover-bg);
      border-radius: 5px;
      > div {
        color: var(--primary-hover-text);
      }
      svg {
        fill: var(--primary-hover-text);
      }
      div {
        color: var(--primary-hover-text);
      }
    }
  }

  .option, .option-disabled {
    padding: $option-padding 0 $option-padding 10px;
  }

  .menu {
    position: absolute;
    left: 0;
    width: 55px;
    height: 54px;
    top: 0;
    grid-area: menu;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    &:hover {
      background-color: var(--topmost-light-hover);
    }
    .menu-icon {
      width: 24px;
      height: 24px;
      fill: var(--header-btn-text);
    }
    &.raised {
      z-index: 200;
    }
  }

  .side-menu {
    position: absolute;
    top: 0;
    left: 0px;
    bottom: 0;
    width: 280px;
    background-color: var(--topmenu-bg);
    z-index: 100;
    border-right: 1px solid var(--topmost-border);
    box-shadow: 0 0 15px 4px var(--topmost-shadow);
    display: flex;
    flex-direction: column;
    padding: 0;

    &:focus {
      outline: 0;
    }

    .title {
      display: flex;
      height: 55px;
      flex: 0 0 55px;
      width: 100%;
      border-bottom: 1px solid var(--nav-border);
      justify-content: flex-start;
      align-items: center;
      .menu {
        display: flex;
        justify-content: center;
        width: 55px;
        margin-right: 10px;
      }
      .menu-icon {
        width: 24px;
        height: 24px;
      }
      .menu-spacer {
        width: 55px;
      }
    }
    .body {
      flex: 1;
      display: flex;
      flex-direction: column;
      margin: 10px 20px;

      .category {
        padding: 10px 0;
        text-transform: uppercase;
        opacity: 0.8;
        margin-top: 10px;
      }

      .home {
        color: var(--link);
      }

      .home:focus {
        outline: 0;
      }

      .cluster {
        align-items: center;
        display: flex;
        height: $option-height;
        &:focus {
          outline: 0;
        }
        .cluster-name {
          font-size: 16px;
        }
        > img {
          max-height: $icon-size;
          max-width: $icon-size;
          margin-right: 8px;
        }
      }

      .pad {
        flex: 1;
      }

      .search {
        position: relative;
        > input {
          background-color: transparent;
          margin-bottom: 8px;
          padding-right: 34px;
        }
        > i {
          position: absolute;
          font-size: $clear-search-size;
          top: ($option-height - $clear-search-size) / 2;
          right: 8px;
          opacity: 0.7;
          cursor: pointer;
          &:hover {
            color: var(--disabled-bg);
          }
        }
      }

      .clusters {
        overflow-y: scroll;
        overflow-x: hidden;
      }

      .none-matching {
        padding: 8px
      }
    }
    .footer {
      margin: 20px;

      display: flex;
      flex: 0;
      flex-direction: row;
      > * {
        flex: 1;
        color: var(--link);

        &:first-child {
          text-align: left;
        }
        &:last-child {
          text-align: right;
        }
        text-align: center;
      }

      .version {
        cursor: pointer;
      }
    }
  }

  .side-menu-glass {
    background-color: transparent;
    position: absolute;
    top: 0;
    left: 0px;
    bottom: 0;
    width: 100vw;
    z-index: 99;
    opacity: 1;
  }

  .side-menu-logo {
    align-items: center;
    display: flex;
    margin-left: 10px;
    opacity: 1;
    transition: opacity 1.2s;
    transition-delay: 0s;
    height: 55px;
    max-width: 200px;
    & IMG {
      object-fit: contain;
      height: 21px;
      max-width: 200px;
    }
  }

  .fade-enter-active {
    .side-menu-logo {
      opacity: 0;
    }
  }

  .fade-enter-active, .fade-leave-active {
    transition: all 0.2s;
    transition-timing-function: ease;
  }

  .fade-leave-active {
    transition: all 0.4s;
  }

  .fade-leave-to {
    left: -300px;
  }

  .fade-enter {
    left: -300px;

    .side-menu-logo {
      opacity: 0;
    }
  }

  .locale-chooser {
    cursor: pointer;
  }

  .localeSelector {
    ::v-deep .popover-inner {
      padding: 50px 0;
    }

    ::v-deep .popover-arrow {
      display: none;
    }

    ::v-deep .popover:focus {
      outline: 0;
    }

    li {
      padding: 8px 20px;

      &:hover {
        background-color: var(--primary-hover-bg);
        color: var(--primary-hover-text);
        text-decoration: none;
      }
    }
  }
</style>
